package main;
import java.util.ArrayList;
import java.util.Calendar;
import javax.sound.midi.MidiUnavailableException;
import javax.swing.JComboBox;
import org.jfugue.realtime.RealTimePlayer;

public class MusicThreads implements Runnable{
	private RealTimePlayer player;
	public static int currentTab=0;
	public int index;
	public ArrayList<ArrayList<Integer>> block; // stores the row number of active buttons, -1 means Rest
	private JComboBox instrumentList;
	static String[] notes={"D4","E4","F4","G4","A4","B4","C5","D5","E5","F5","G5","A5","B5","C6","D6","E6"};
	static String[] drumnotes={"[BASS_DRUM]","[CLOSED_HI_HAT]"}; // for drums, two instruments cannot play at once, so will only play one note at once
	public boolean clear=false;
	public boolean clickmenu = false;
	public static ui UI;
	public boolean play = true;
	public static int part =0 ;
	public static int volume;
	public int instrument;
	
	public MusicThreads(JComboBox instList, int ind){
		instrumentList=instList;
		if (ind ==0)instrumentList.setSelectedIndex(1);
			else instrumentList.setSelectedIndex(0);
		block=new ArrayList<ArrayList<Integer>>();
		for(int i=0;i<16;i++){
			ArrayList<Integer> temp=new ArrayList<Integer>();
			temp.add(-1);
			block.add(temp);
		}
		index=ind;
	//	sync[ind]=1;
	}
	/*public void setIndex(int i){
		instrumentList.setSelectedIndex(i);
	}*/

	@Override
	public void run(){
		try {
            player = new RealTimePlayer();
        } catch (MidiUnavailableException e) {
            e.printStackTrace();
        }
		
	 	volume=120;
	 	player.play(":CON(7, "+volume+")");	
	 	
	 	String[] note=notes;
	 	int numofNotes=notes.length;
	 	instrument=0;
		int k=0;
		String start,end;
		player.play("I0");
		player.play("Rw-");
		delay(125);
		player.play("R-w");
		
		
		while(true){
	label:	for(int i=k;i<16;i=k){
				start="";
				end="";	
				// if function to tabbed play
				if(ui.textinput.size()!=0&&UI.checkbox.isSelected()&&k==0){
	//				System.out.println("in2");
					//set all threads to play = false any time
					play=false;
					
					if(index==0){
//						System.out.println("in");
						for(int j=0;j<ui.textinput.get(part).size();j++){
							//only set play = true when if the thread is in the tab
							System.out.println(ui.textinput.get(part).get(j));
							UI.getMusicThreads().get(ui.textinput.get(part).get(j)).play=true;
						}
						part++;
						if(part==ui.textinput.size()) part=0;
					}
				}
				while(!play&&ui.textinput.size()!=0&&UI.checkbox.isSelected()&&index!=0&&k==0){
					delay(0);  // dummy, won't work if not add = =
				}
				
				if(play||!UI.checkbox.isSelected()){
					for(int j=0;j<block.get(i).size();j++){  // concat notes that are played together
						if(block.get(i).get(j)==-1){
							start=start.concat("R");
							end=end.concat("R");
						}
						else{
							start=start.concat(note[block.get(i).get(j)%numofNotes]);
							end=end.concat(note[block.get(i).get(j)%numofNotes]);
						}
						if(instrument==-1) break;
						if(j!=block.get(i).size()-1){start=start.concat("w-+");end=end.concat("-w+");}
					}
					//System.out.println(start);
					if(start.equals("R")||instrumentList.getSelectedIndex()==0){ // if nothing to play, thread wait for 125ms (VERY IMPORTANT for CPU usage)
						synchronized(this){
							try {
								wait(125);
								k=i+1;
								if(k==16) k=0;
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}else{
						clickmenu = false;
						if(clear){
							clear();
							break;
						}
						player.play(start.concat("w-"));
						
						int p,count=1;
						k=i+1;
						for(p=0;p<=16;p++,count++,k++){  // determine the note duration	
							if(k==16) k=p=0;
							if(block.get(k).get(0)!=-1||count>4) break; // count>4 because note duration at most 4 beats
						}
						delay(count*125);
						player.play(end.concat("-w"));
						// if in tab mode go back to k=0
						if(ui.textinput.size()!=0&&UI.checkbox.isSelected()&&k<i){
							k=0;
							continue label;
						}
						//System.out.println("tab"+instrumentList.getClientProperty("tab")+" seled index"+instrumentList.getSelectedIndex());
						
						if(instrumentList.getSelectedIndex()!=instrument){
							switch(instrumentList.getSelectedIndex()){
								case 1:
									instrument=0; break;
								case 2: 
									instrument=40; break;
								case 3: 
									instrument=-1; break;
								case 4:
									instrument=29; break;
								case 5:
									instrument=26; break;
								case 6:
									instrument=11; break;
								case 7:
									instrument=10; break;
								case 8:
									instrument=56; break;
								case 9:
									instrument=73; break;
								case 10:
									instrument=64; break;
								case 11:
									instrument=19; break;
								case 12:
									instrument=60; break;
								case 13:
									instrument=71; break;
								case 14:
									instrument=123; break;
								case 15:
									instrument=78; break;
								case 16:
									instrument=88; break;
							}
							if(instrument==-1) {
								note=drumnotes;
								numofNotes=drumnotes.length;
								player.play("V9 ");
							}
							else{
								note=notes;
								numofNotes=notes.length;
								player.play("V"+index+" I"+instrument);
							}
						}
						
						/*if(clear){
							clear();
							break;
						}*/
						
						
					}
				}else{
					synchronized(this){
						try {
							wait(125);
							k=i+1;
							if(k==16) k=0;
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
	}
	
	public void clear(){
		block.clear();
		for(int i=0;i<16;i++){
			ArrayList<Integer> temp=new ArrayList<Integer>();
			temp.add(-1);
			block.add(temp);
		}
		clear=false;
	}
	
	/*public void run(){
			/*try {
				player2=new RealTimePlayer();
			} catch (MidiUnavailableException e) {
				e.printStackTrace();
			}

		String[] drums={"[BASS_DRUM]","[BASS_DRUM]","[CLOSED_HI_HAT]","R","[BASS_DRUM]","[BASS_DRUM]","[CLOSED_HI_HAT]","[CLOSED_HI_HAT]"};
		sync2=true;
		
		while(!sync||!sync2);
		boolean first2=true;
		System.out.println("in");
		while(true){
		 	for(int i=0;i<drums.length;i++){
			 	player2.play("V9 "+drums[i]+"w-");
			 	if(first2){
			 		music.delay(65);
			 		first2=false;
			 	}else{
			 		music.delay(250);
			 	}
			 	player2.play("V9 "+drums[i]+"-w");
			 	
		 	}
	 	}
	}*/
	 	
	public void delay(long ms){
		long s = Calendar.getInstance().getTime().getTime();
		long e = Calendar.getInstance().getTime().getTime();
		while((e - s) < ms)	{
			e = Calendar.getInstance().getTime().getTime();
		}
	}
	
	public JComboBox getInstrumentList(){
		return instrumentList;
	}
/*
	public void setPlay(boolean b){
		play = b; 
	}*/
	public void setVolume(int n){
		volume =n;
		player.play(":CON(7, "+volume+")");
	}
}
